#ifndef MANAGER_H_INCLUDED
#define MANAGER_H_INCLUDED

#include "XGE_Common.h"
#include "Element.h"

namespace XGE
{
    template<typename T> class Manager
    {
        protected:
            XGE::ElementMap elements;
            Ogre::String strName;

        public:
            Manager(const Ogre::String& nName)
            {
                //Managers must have a valid name
                if(nName != "")
                {
                    strName = nName;
                }
                else
                {
                    throw(Ogre::Exception(Ogre::Exception::ERR_INVALIDPARAMS, "Attempted to instantiate a Manager<> without a name!", "Manager.h"));
                }
            };

            ~Manager()
            {
                if(!elements.empty())
                {
                    XGE::ElementMap::iterator i;
                    for(i = elements.begin(); i != elements.end(); ++i)
                    {
                        delete (*i).second;
                    }

                    elements.clear();
                }
            }

            //Creates a new Element
            Element* createElement(Ogre::String nElementName)
            {
                if(!elements[nElementName])
                {
                    elements[nElementName] = new T(nElementName);
                    return elements[nElementName];
                }

                throw(Ogre::Exception(Ogre::Exception::ERR_DUPLICATE_ITEM, "\"" + strName + "\" an element with the name \"" + nElementName + "\" already exists!", "Manager.h"));

                return 0;
            }

            //Adds an existing Element
            void addElement(T* nElement)
            {
                if(!nElement)
                {
                    throw(Ogre::Exception(Ogre::Exception::ERR_INVALIDPARAMS, "\"" + strName + "\" could not add an invalid element!", "Manager.h"));
                }

                if(nElement->getName == "")
                {
                    throw(Ogre::Exception(Ogre::Exception::ERR_INVALIDPARAMS, "\"" + strName + "\" could not add an element with an invalid name!", "Manager.h"));
                }

                if(elements[nElement->getName()])
                {
                    throw(Ogre::Exception(Ogre::Exception::ERR_DUPLICATE_ITEM, "\"" + strName + "\" an element with the name \"" + nElement->getName() + "\" already exists!", "Manager.h"));
                }

                elements[nElement->getName()] = nElement;
            }

            //Returns an existing Element
            Element* getElement(Ogre::String nElementName)
            {
                if(elements[nElementName])
                {
                    return elements[nElementName];
                }

                throw(Ogre::Exception(Ogre::Exception::ERR_ITEM_NOT_FOUND, "\"" + strName + "\" cannot get element with the name \"" + nElementName + "\" because it does not exist!", "Manager.h"));
                return 0;
            }

            //Deletes an existing Element
            void deleteElement(Ogre::String nElementName)
            {
                if(elements[nElementName])
                {
                    delete elements[nElementName];
                    elements.erase(nElementName);
                }
                else
                {
                    throw(Ogre::Exception(Ogre::Exception::ERR_ITEM_NOT_FOUND, "\"" + strName + "\" cannot delete element with the name \"" + nElementName + "\" because it does not exist!", "Manager.h"));
                }
            }
    };
}

#endif // MANAGER_H_INCLUDED
